<?php
declare(strict_types=1);

namespace Modules\Reservation\Http\Controllers;

use Catch\Base\CatchController as Controller;
use Catch\Exceptions\FailedException;
use Illuminate\Support\Facades\DB;
use Modules\Customer\Models\Customer;
use Modules\CustomerLesson\Models\CustomerLesson;
use Modules\LessonHour\Http\Controllers\LessonHourController;
use Modules\LessonHour\Models\LessonHour;
use Modules\LessonTime\Models\LessonTime;
use Modules\Reservation\Models\Reservation;
use Illuminate\Http\Request;
use Modules\Subject\Models\Subject;
use Modules\Teacher\Models\Teacher;
use Modules\TeacherLesson\Models\TeacherLesson;


class ReservationController extends Controller
{
    public function __construct(
        protected readonly Reservation $model
    ){}

    /**
     * @return mixed
     */
    public function index(Request $request): mixed
    {
        $where = [];
        $param = $request->all();

        if (!empty($param['user_id']))
        {
            $where['reservation.customer_id'] = $param['user_id'];
        }
        if (!empty($param['teacher_id']))
        {
            $where['reservation.teacher_id'] = $param['teacher_id'];
        }
        if (!empty($param['reservation_status']))
        {
            $where['reservation.status'] = (int) $param['reservation_status'];
        }

        $reservation = Reservation::query()->where($where);

        if (!empty($param['start_time']) && !empty($param['end_time']))
        {
            $reservation = $reservation->whereBetween("reservation.lesson_date", [$param['start_time'], $param['end_time']]);
        }

        $result = $reservation
            ->select(['reservation.id','reservation.lessons','subject.name as subject_name','grade.name as grade_name','reservation.status','reservation.lesson_date','reservation.cancel_time','reservation.cancel_name','reservation.reserve_time','reservation.reserve_name','teacher.name as teacher_name','customer.username as customer_name','lesson_time.start_time','lesson_time.end_time','lesson_time.time_long'])
            ->join("teacher","reservation.teacher_id","=","teacher.id","left")
            ->join("customer","reservation.customer_id","=","customer.id","left")
            ->join("lesson_time","reservation.lesson_time_id","=","lesson_time.id","left")
            ->join("subject","reservation.subject_id","=","subject.id","left")
            ->join("grade","subject.grade_id","=","grade.id","left")
            ->paginate($param['limit'] ?? 10 ,['*'] ,'' ,$param['page'])->toArray();

        if (!empty($result['data']))
        {
            foreach ($result['data'] as $key => $value)
            {
                $result['data'][$key]['reserve_time'] = date("Y-m-d H:i:s", $value['reserve_time']);
                $result['data'][$key]['lesson_time'] = $value['start_time'] . "~" . $value['end_time'];
                $result['data'][$key]['cancel_time'] = $value['cancel_time'] > 0 ? date("Y-m-d H:i:s", $value['cancel_time']) : "--";
                $result['data'][$key]['subject'] = $value['grade_name'] . " - " . $value['subject_name'];
            }
        }

        return $result;
    }

    // 课时统计
    public function lessonCount()
    {
        // 课时统计
        $counts = Reservation::query()->select("status",DB::raw('SUM(lessons) as lessons'))->groupBy("status")->get();
        foreach ($counts as &$count)
        {
            $count['name'] = $count['status'] == LessonHourController::RESERVATION_1 ? "未开始" : ($count['status'] == LessonHourController::RESERVATION_2 ? "进行中" : ($count['status'] == LessonHourController::RESERVATION_3 ? "已取消" : "已完成"));
        }

        return $counts;
    }

    /**
     * @param Request $request
     * @return mixed
     */
    public function add(Request $request)
    {
        $param = $request->all();

        if (empty($param['user_id']) || empty($param['teacher_id']) || empty($param['subject_id']) || empty($param['lesson_date']) || empty($param['lesson_time']))
        {
            throw new FailedException("预约信息必填");
        }

        $lessonTimeList = $this->getKeyArr(LessonTime::query()->select()->get());
        $customerLesson = CustomerLesson::query()->where(['customer_id' => $param['user_id'],'teacher_id' => $param['teacher_id']])->first();

        if (empty($customerLesson))
        {
            throw new FailedException("学员课时信息不存在");
        }

        $lessonTimes = explode(",", $param['lesson_time']);
        $lessonDates = explode(",", $param['lesson_date']);

        $lessonKey = 0;
        $whereList = $reqParams = $lessonHours = [];
        foreach ($lessonDates as $lessonDate)
        {
            foreach ($lessonTimes as $lessonTime)
            {
                $lessonKey ++;
                $customerLesson['lessons'] -= 30;
                $whereList[] = [
                    "lesson_date" => $lessonDate,
                    "lesson_time_id" => $lessonTime,
                    "teacher_id" => $param['teacher_id'],
                ];
                $reqParams[$lessonKey] = [
                    "lesson_date" => $lessonDate,
                    "lesson_time_id" => $lessonTime,
                    "teacher_id" => $param['teacher_id'],
                    "customer_id" => $param['user_id'],
                    "subject_id" => $param['subject_id'],
                    "lessons" => 30,
                    "status" => LessonHourController::RESERVATION_1,
                    "reserve_time" => time(),
                    "reserve_name" => $this->getLoginUser()['username'],
                ];

                $lessonHours[$lessonKey] = [
                    "customer_id" => $param['user_id'],
                    "lessons" => 30,
                    "last_lessons" => $customerLesson['lessons'],
                    "lesson_type" => LessonHourController::LESSON_TYPE_4,
                    "desc" => "[教师预约课程]",
                    "lesson_status" => LessonHourController::LESSON_STATUS_3,
                    "teacher_id" => $param['teacher_id'],
                ];
            }
        }

        if ($customerLesson['lessons'] < 0)
        {
            throw new FailedException("课时不足，无法预约课程");
        }

        foreach ($whereList as $where)
        {
            // 查询老师当天是否有课
            $teacherLesson = TeacherLesson::query()->where(['teacher_id'=>$where['teacher_id'],"lesson_date" => $where['lesson_date']])->first();
            $lesson = $lessonTimeList[$where['lesson_time_id']]['start_time'] . "~" . $lessonTimeList[$where['lesson_time_id']]['end_time'];
            if (!empty($teacherLesson))
            {
                $lessonTimeIds = explode(",", $teacherLesson['lesson_time_ids']);
                if (!in_array($where['lesson_time_id'], $lessonTimeIds))
                {
                    throw new FailedException("老师[{$where['lesson_date']}]日 [{$lesson}] 时段没有课，请重新选择");
                }
            }

            $reservation = Reservation::query()->where($where)->first();
            if (!empty($reservation))
            {
                throw new FailedException("[{$lesson}]时段已被预约");
            }
        }

        $lessonHourModel = new LessonHour();

        // 开启事务
        DB::beginTransaction();

        try {

            // 记得调整入库顺序
            foreach ($reqParams as $key => $reqParam)
            {
                $res_id = $this->model->createBy($reqParam);
                $lessonHours[$key]['reservation_id'] = $res_id;
                $lessonHourModel->createBy($lessonHours[$key]);
            }
            $customerLesson->save();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw new FailedException("预约失败");
        }

        return "约课成功";
    }

    // 获取教师的科目
    public function getUserSubjects(Request $request)
    {
        $param = $request->all();
        if (empty($param['teacher_id']))
        {
            throw new FailedException("教师ID必填");
        }

        $teacher = Teacher::query()->where(['id' => $param['teacher_id']])->first();
        if (empty($teacher))
        {
            throw new FailedException("教师不存在");
        }

        $subjects = Subject::query()
            ->select(['subject.id as subject_id','subject.name as subject_name','grade.name as grade_name','grade.id as grade_id'])
            ->whereIn('subject.id',explode(",",$teacher['subject_ids']))
            ->join('grade','grade.id','=','subject.grade_id')
            ->get();

        $result = [];
        foreach ($subjects as $subject)
        {
            $result[$subject['grade_id']]['value'] = $subject['grade_id'];
            $result[$subject['grade_id']]['label'] = $subject['grade_name'];
            $result[$subject['grade_id']]['children'][] = [
                'value' => $subject['subject_id'],
                'label' => $subject['subject_name'],
            ];
        }

        return array_values($result);
    }

    // 上课时间
    public function getLessonTime()
    {
        $timeLs = LessonTime::query()->select()->get();

        foreach ($timeLs as $timeL)
        {
            $result[] = [
                "id" => $timeL['id'],
                "name" => $timeL['start_time'] . "~" . $timeL['end_time'],
            ];
        }

        return $result;
    }

    // 取消预约
    public function cancel(Request $request)
    {
        $param = $request->all();
        $reservation = Reservation::query()->where(['id' => $param['id'], 'status'=> 1])->first();
        if (empty($reservation))
        {
            throw new FailedException("当前课时状态不可取消");
        }

        $customerLesson = CustomerLesson::query()->where(['customer_id' => $reservation['customer_id'],'teacher_id' => $reservation['teacher_id']])->first();
        $lessonTime = LessonTime::query()->where(['id' => $reservation['lesson_time_id']])->first();
        $lessonHour = LessonHour::query()->where(['reservation_id' => $reservation['id']])->first();
        $lessonDateTime = $reservation['lesson_date'] . " " . $lessonTime['start_time'];
        if (strtotime($lessonDateTime) <= time())
        {
            throw new FailedException("课程已开始，无法取消");
        }

        $reservation['status'] = LessonHourController::RESERVATION_3;
        $reservation['cancel_name'] = $this->getLoginUser()['username'];
        $reservation['cancel_time'] = time();
        $customerLesson['lessons'] += $reservation['lessons'];
        $lessonHour['lesson_status'] = LessonHourController::LESSON_STATUS_6;
        $lessonHour['remark'] = $lessonHour['remark'] . "[教师取消预约]";
        $lessonHour['last_lessons'] = $customerLesson['lessons'];

        // 开启事务
        DB::beginTransaction();

        try {
            $reservation->save();
            $lessonHour->save();
            $customerLesson->save();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw new FailedException("取消失败");
        }

        return "取消成功";
    }

    /**
     * @param Request $request
     * @param $id
     * @return mixed
     */
    public function updateHours(Request $request)
    {
        $param = $request->all();
        $hours = $param['lessons'];
        $reservation = Reservation::query()->where(['id' => $param['id']])->first();
        if (empty($reservation))
        {
            throw new FailedException("预约信息不存在");
        }

        $lessonHour = LessonHour::query()->where(['reservation_id' => $param['id']])->first();
        $customerLesson = CustomerLesson::query()->where(['customer_id' => $reservation['customer_id'],'teacher_id' => $reservation['teacher_id']])->first();

        $lessonHour['lessons'] = $hours;
        $lessonHour['last_lessons'] = $customerLesson['lessons'];
        $lessonHour['remark'] = $lessonHour['remark'] . "[教师修改实销课时]";
        $lessonHour['lesson_status'] = LessonHourController::LESSON_STATUS_5;
        $customerLesson['lessons'] = $customerLesson['lessons'] + $hours - $reservation['lessons'];
        $reservation['lessons'] = $hours;

        // 开启事务
        DB::beginTransaction();

        try {
            $reservation->save();
            $lessonHour->save();
            $customerLesson->save();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw new FailedException("修改失败");
        }

        return "修改成功";
    }

    public function getKeyArr($data = [])
    {
        $result = [];
        foreach ($data as $key => $value)
        {
            $result[$value['id']] = $value;
        }
        return $result;
    }
}
